package main

import (
	"log"

	amqp "github.com/rabbitmq/amqp091-go"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Panicf("%s: %s", msg, err)
	}
}

func main() {
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	failOnError(err, "Failed to connect to RabbitMQ")
	defer conn.Close()

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")
	defer ch.Close()

	q, err := ch.QueueDeclare(
		"gin_wire_queue", // name
		false,           // durable: 队列是否持久化
		false,           // delete when unused: 队列在没有消费者时是否删除
		false,           // exclusive: 是否为独占队列
		false,           // no-wait: 是否不等待确认
		nil,             // arguments: 附加参数
	)
	failOnError(err, "Failed to declare a queue")

	msgs, err := ch.Consume(
		q.Name, // queue
		"",     // consumer
		true,   // auto-ack
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)

	failOnError(err, "Failed to register a consumer")
	
	var forever chan struct{}
	go func() {
		for d := range msgs {
			log.Printf("Received a message: %s", d.Body)
		}
	}()
	log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
	<-forever


}

/**
1 阻塞当前 goroutine:

<-forever 这一行代码会导致当前 goroutine 阻塞，因为 forever 通道没有发送任何值，也没有被关闭，所以 <-forever 表达式会一直等待，使得程序不会结束。

2 控制程序流程:

在这个例子中，程序会持续监听来自 RabbitMQ 的消息，并打印接收到的消息。通过使用 forever （channel通道），可以确保消息处理逻辑一直运行，直到程序被外部中断（例如用户按下 Ctrl+C）。

3 简单信号机制:

chan struct{} 可以作为一种简单的信号通道使用，因为它不携带任何数据，仅用于通知或同步目的。在本例中，它被用来让主 goroutine 等待其他 goroutine 完成它们的任务。
总结来说，在这段代码中，

var forever chan struct{} 的主要目的是创建一个永远不会被发送值的通道，用于阻塞主 goroutine 的执行，从而确保程序能够持续运行并接收消息。

 */ 